<!-- eslint-disable vue/no-mutating-props -->
<script lang="jsx">
  export default {
    name: 'NcFormTable',
    props: {
      tableData: {
        type: Array,
        default: () => []
      },
      // [{ label: '用户姓名', name: 'loginname'}]
      columns: {
        type: Array,
        default: () => []
      },
      // 分页page
      page: {
        type: Object,
        default: () => {
          return {
            pageNum: 1,
            pageSize: 10
          };
        }
      },
      total: {
        type: Number,
        default: 0
      },
      pageSizeArray: {
        type: Array,
        default: () => [10, 30, 60, 100]
      },
      // 是否显示多选列
      isSelectFlag: {
        type: Boolean,
        default: true
      },
      // 是否显示序号列
      isSequenceFlag: {
        type: Boolean,
        default: true
      },
      // 是否显示分页
      isShowPage: {
        type: Boolean,
        default: true
      },
      // size
      size: {
        type: String,
        default: 'small'
      },
      headerStyle: {
        // 表头样式 优先级大于size
        type: [Function, Object],
        default: () => {
          return {
            color: '#333',
            'background-color': '#EBF6FF'
          };
        }
      },
      // 通过在父组件改变值，从而重置选择
      resetFlag: {
        type: Boolean,
        default: false
      }
    },
    emits: [
      'selectionChange',
      'pageChange',
      'select',
      'selectVisibleClose',
      'inputAppendBtnClick',
      'attachmentInfo',
      'attachmentUpload',
      'handleOperation'
    ],
    watch: {
      resetFlag() {
        this.resetSelection();
      },
      isSequenceFlag() {
        console.log('isSequenceFlag');
        this.doLayout();
      },
      isSelectFlag() {
        console.log('isSelectFlag');
        this.doLayout();
      }
    },
    methods: {
      doLayout() {
        this.$nextTick(() => {
          this.$refs.ncTable.doLayout();
        });
      },
      rowClick(row) {
        this.$refs.ncTable.toggleRowSelection(row);
      },
      // 重置选择
      resetSelection() {
        this.$refs.ncTable.clearSelection();
      },
      selectionChange(selection) {
        this.$emit('selectionChange', selection);
      },
      handleSizeChange(val) {
        this.page.pageSize = val;
        this.page.pageNum = 1;
        this.$emit('pageChange', this.page);
      },
      handleCurrentChange(val) {
        this.page.pageNum = val;
        this.$emit('pageChange', this.page);
      },
      select(selection, row) {
        this.$emit('select', selection, row);
      },
      isSequenceFlagMeth() {
        if (this.isSequenceFlag) {
          return <NstdTableColumn fixed align="center" label="序号" key="index" type="index" width="60" />;
        }
        return null;
      },
      isSelectFlagMeth() {
        if (this.isSelectFlag) {
          return <NstdTableColumn fixed align="center" key="selection" type="selection" width="55" />;
        }
        return null;
      },
      processor(props, value) {
        const self = this;
        if (value.type) {
          const type = this.replaceStr(value.type);
          return self['generate' + type](props, value); // 拼接方法
        }
        return props.row[value.prop];
      },
      replaceStr(str) {
        const reg = /\b(\w)|\s(\w)/g;
        return str.replace(reg, function (m) {
          return m.toUpperCase();
        });
      },
      // 生成下拉菜单 type: select // option: [{id:'',name: ''}]
      generateSelect(props, item) {
        const tempObj = item.propsObj || { value: 'id', label: 'name' };
        const options = item.dataList ? item.dataList : [];
        return (
          <NstdTooltip
            disabled={!props.row[item.prop]}
            content={props.row[item.nameLabel]}
            placement="top"
            effect="dark"
          >
            <NstdSelect
              value={props.row[item.prop]}
              size={item.size}
              style={item.style ? item.style : 'width: 170px'}
              multiple={item.multiple ? item.multiple : false}
              disabled={item.disabled ? item.disabled : false}
              clearable={item.clearable ? !item.clearable : true}
              filterable={item.multiple ? item.filterable : true}
              collapseTags={item.collapseTags ? !item.collapseTags : true}
              placeholder={item.placeholder ? item.placeholder : '请选择' + item.label}
              filter-method={item.filterMethod}
              onChange={(e) => {
                this.$set(props.row, item.prop, e);
                if (item.nameLabel) {
                  if (item.multiple) {
                    const temps = options.filter((v) => e.includes(v[tempObj.value]));
                    const nameLabel = [];
                    temps.forEach((v) => {
                      nameLabel.push(v[item.prop]);
                    });
                    this.$set(props.row, item.nameLabel, nameLabel);
                  } else {
                    const index = options.findIndex((v) => v[tempObj.value] === e);
                    const nameLabel = index > -1 ? options[index][tempObj.label] : '';
                    this.$set(props.row, item.nameLabel, nameLabel);
                  }
                }
              }}
              onVisible-change={(e) => {
                if (!e) {
                  this.$emit('selectVisibleClose', props.row, item);
                }
              }}
            >
              {options.map((value, index) => {
                return (
                  <NstdOption
                    key={value[tempObj.value] + 'nc_form_table_' + index}
                    label={value[tempObj.label]}
                    value={value[tempObj.value]}
                  ></NstdOption>
                );
              })}
            </NstdSelect>
          </NstdTooltip>
        );
      },
      // 生成输入框 type: input
      generateInput(props, item) {
        return (
          <NstdTooltip disabled={!props.row[item.prop]} content={props.row[item.prop]} placement="top" effect="dark">
            <NstdInput
              type={item.isNumber ? 'number' : item.type}
              value={props.row[item.prop]}
              size={item.size}
              style={item.style}
              disabled={item.disabled ? item.disabled : false}
              clearable={item.clearable ? item.clearable : true}
              maxlength={item.maxlength ? item.maxlength : 200}
              placeholder={item.placeholder ? item.placeholder : '请输入' + item.label}
              onInput={(e) => {
                this.$set(props.row, item.prop, e.trim());
              }}
            />
          </NstdTooltip>
        );
      },
      // 生成输入框 type: inputAppend
      generateInputAppend(props, item) {
        return (
          <NstdTooltip disabled={!props.row[item.prop]} content={props.row[item.prop]} placement="top" effect="dark">
            <NstdInput
              type={'input'}
              readonly={true}
              value={props.row[item.prop]}
              size={item.size}
              style={item.style}
              maxlength={item.maxlength ? item.maxlength : 200}
              placeholder={item.placeholder ? item.placeholder : '请输入' + item.label}
            >
              <NstdButton
                disabled={item.disabled ? item.disabled : false}
                icon="NstdIcon-more"
                slot="append"
                onClick={() => {
                  this.$emit('inputAppendBtnClick', { row: props.row, item: item });
                }}
              />
            </NstdInput>
          </NstdTooltip>
        );
      },
      // 生成文本输入框 type: textarea
      generateTextarea(props, item) {
        return (
          <NstdInput
            type={item.type}
            rows={item.rows ? item.rows : 3}
            value={props.row[item.prop]}
            size={item.size}
            style={item.style}
            disabled={item.disabled ? item.disabled : false}
            autosize={item.autosize ? item.autosize : false}
            maxlength={item.maxlength ? item.maxlength : 200}
            show-word-limit={item.showWordLimit ? item.showWordLimit : false}
            placeholder={item.placeholder ? item.placeholder : '请输入' + item.label}
            onInput={(e) => {
              this.$set(props.row, item.prop, e.trim());
            }}
          />
        );
      },
      // 生成带有按钮的输入框 type: inputAppendBtn ; event: inputAppendBtnClick
      generateInputAppendBtn(props, item) {
        return (
          <NstdInput
            type="text"
            value={props.row[item.prop]}
            size={item.size}
            style={item.style ? item.style : 'width: 170px'}
            disabled={item.disabled ? item.disabled : false}
            placeholder={item.placeholder ? item.placeholder : '请选择' + item.label}
            onInput={(e) => {
              this.$set(props.row, item.prop, e.trim());
            }}
          >
            <NstdButton
              className="btn-append"
              slot="append"
              onClick={() => {
                this.$emit('inputAppendBtnClick', { row: props.row, item: item });
              }}
            >
              {item.appendLabel ? item.appendLabel : '选择'}
            </NstdButton>
          </NstdInput>
        );
      },
      // 生成时间框 type:date
      generateDate(props, item) {
        return (
          <NstdDatePicker
            type={item.type}
            size={item.size}
            attrs={{ value: props.row[item.prop] }}
            disabled={item.disabled ? item.disabled : false}
            style={item.style ? item.style : 'width: 100%'}
            default-time={item.defaultTime || '10:00:00'}
            value-format={item.valueFormat ? item.valueFormat : 'timestamp'} // 默认时间戳格式
            placeholder={item.placeholder ? item.placeholder : '请选择' + item.label}
            change={item.change}
            onInput={(e) => {
              this.$set(props.row, item.prop, e);
            }}
          ></NstdDatePicker>
        );
      },
      // 生成日期时间框 type:datetime
      generateDatetime(props, item) {
        return (
          <NstdDatePicker
            type={item.type}
            size={item.size}
            format={item.format}
            attrs={{ value: props.row[item.prop] }}
            disabled={item.disabled ? item.disabled : false}
            style={item.style ? item.style : 'width: 100%'}
            default-time={item.defaultTime}
            value-format={item.valueFormat ? item.valueFormat : 'timestamp'} // 默认时间戳格式
            placeholder={item.placeholder ? item.placeholder : '请选择' + item.label}
            onChange={(e) => {
              if (item.change && item.change instanceof Function) {
                item.change(e, props.row);
              }
            }}
            onInput={(e) => {
              this.$set(props.row, item.prop, e);
            }}
          ></NstdDatePicker>
        );
      },
      // 生成附件框 type:attachment  event: attachmentInfo / attachmentUpload
      generateAttachment(props, item) {
        return (
          <div>
            <NstdButton
              size="small"
              onClick={() => {
                this.$emit('attachmentInfo', item);
              }}
            >
              <i class="NstdIcon-paperclip" />
            </NstdButton>
            <NstdButton
              size="small"
              onClick={() => {
                this.$emit('attachmentUpload', item);
              }}
            >
              <i class="NstdIcon-folder-opened" />
            </NstdButton>
          </div>
        );
      },
      // 生成操作框 type:operation  event: handleOperation
      generateOperation(props, item) {
        const tempList = item.btnList || [
          { action: 'edit', label: '编辑' },
          { action: 'delete', label: '删除' }
        ];
        return (
          <div style="text-align: center">
            {tempList.map((value) => {
              return (
                <NstdButton
                  size={item.size}
                  type={value.btnType ? value.btnType : 'text'}
                  disabled={item.disabled ? item.disabled : false}
                  onClick={() => {
                    this.$emit('handleOperation', { row: props.row, item: value });
                  }}
                >
                  {value.label}
                </NstdButton>
              );
            })}
          </div>
        );
      },
      // 生成操作框 type:operationBtn  event: handleOperation
      generateOperationBtn(props, item) {
        const tempList = item.btnList || [
          { action: 'edit', label: '编辑', icon: 'NstdIcon-edit-outline' },
          { action: 'delete', label: '删除', icon: 'NstdIcon-delete' }
        ];
        return (
          <div style="text-align: center">
            {tempList.map((value) => {
              return (
                <NstdTooltip effect="dark" placement="top" content={value.label} disabled={!value.label}>
                  <NstdButton
                    disabled={item.disabled ? item.disabled : false}
                    style="border: none; padding: 3px 5px;"
                    icon={value.icon}
                    type="primary"
                    onClick={() => {
                      this.$emit('handleOperation', { row: props.row, item: value });
                    }}
                  />
                </NstdTooltip>
              );
            })}
          </div>
        );
      },
      // 生成单选框 type:checkbox:
      generateCheckbox(props, item) {
        return (
          <NstdCheckbox
            size={item.size}
            disabled={item.disabled}
            onChange={(e) => {
              this.$set(props.row, item.prop, Number(e));
            }}
          ></NstdCheckbox>
        );
      },
      // 生成弹框输入框 type:popover
      generatePopover(props, item) {
        return (
          <NstdPopover
            width={300}
            placement={'bottom'}
            disabled={item.disabled ? item.disabled : false}
            trigger={'click'}
          >
            <NstdInput
              type={'textarea'}
              style={'width: 300px'}
              value={props.row[item.prop]}
              autosize={{ minRows: 4, maxRows: 6 }}
              disabled={item.disabled ? item.disabled : false}
              placeholder={item.placeholder ? item.placeholder : '请输入' + item.label}
              onInput={(e) => {
                this.$set(props.row, item.prop, e.trim());
              }}
            />
            <NstdTooltip slot={'reference'} content={props.row[item.prop]} placement="top">
              <div style={'height: 20px'}>{props.row[item.prop]}</div>
            </NstdTooltip>
          </NstdPopover>
        );
      },
      // 生成可插入框 type:plugInType
      generatePlugInType(props, item) {
        return (
          <div class="plugin-input-container">
            <NstdTooltip effect="dark" placement="top" content={props.row[item.prop]} disabled={!props.row[item.prop]}>
              <NstdInput
                id={`plugIn${props.$index}`}
                type={item.types}
                value={props.row[item.prop]}
                size={item.size}
                style={item.style}
                disabled={item.disabled ? item.disabled : false}
                clearable={item.clearable ? item.clearable : true}
                maxlength={item.showWordLimit ? item.maxlength : 200}
                show-word-limit={item.showWordLimit ? item.showWordLimit : false}
                placeholder={item.placeholder ? item.placeholder : '请输入' + item.label}
                onFocus={() => {
                  this.$set(props.row, 'optFlag', true);
                }}
                onInput={(e) => {
                  this.$set(props.row, item.prop, e.trim());
                }}
              />
            </NstdTooltip>
            {this.generatePlugInOpt(props, item)}
          </div>
        );
      },
      generatePlugInOpt(props, item) {
        if (props.row.optFlag) {
          return (
            <NstdButton
              icon={item.icon || 'NstdIcon-circle-plus'}
              onClick={() => {
                const elInput = document.getElementById(`plugIn${props.$index}`);
                const startPos = elInput.selectionStart;
                const endPos = elInput.selectionEnd;
                const html = '_______';
                let temp = '';
                if (startPos && endPos) {
                  temp = `${props.row[item.prop].substring(0, startPos)}${html}${props.row[item.prop].substring(
                    endPos
                  )}`;
                } else {
                  temp = props.row[item.prop].concat(html);
                }
                this.$set(props.row, item.prop, temp);
                this.$set(props.row, 'optFlag', false);
              }}
            ></NstdButton>
          );
        }
      },
      renderHeader(h, column, value) {
        return h('span', {
          domProps: {
            innerHTML: value.required ? '<span style="color:red">*</span>' + column.label : column.label
          }
        });
      },
      // 分页
      generatePage() {
        if (this.isShowPage) {
          return (
            <div class="table--pagination">
              <NstdPagination
                small
                background
                class="mt-4"
                layout="total, sizes, prev, pager, next, jumper"
                page-sizes={this.pageSizeArray}
                v-model:current-page={this.page.pageNum}
                v-model:page-size={this.page.pageSize}
                onSizeChange={this.handleSizeChange}
                onCurrentChange={this.handleCurrentChange}
                total={this.page.total}
              />
            </div>
          );
        }
      }
    },
    render() {
      return (
        <div>
          <NstdBizTable
            ref="ncTable"
            fit={true}
            border={true}
            // stripe={true}
            size={this.size}
            header-row-style={this.headerStyle}
            onSelect={this.select}
            highlight-current-row={true}
            onSelection-change={this.selectionChange}
            onRow-click={this.rowClick}
            data={this.tableData}
          >
            {this.isSelectFlagMeth()}
            {this.isSequenceFlagMeth()}
            {this.columns.map((value) => {
              const slots = {
                default: (props) => {
                  return this.processor(props, value);
                }
              };
              return (
                <NstdTableColumn
                  prop={value.prop}
                  label={value.label}
                  width={value.width}
                  align={value.align}
                  class-name={value.event ? 'hightlight' : ''}
                  sortable={value.sortable ?? false}
                  v-slots={slots}
                  {...{
                    scopedSlots: {}
                  }}
                ></NstdTableColumn>
              );
            })}
          </NstdBizTable>
          {this.generatePage()}
        </div>
      );
    }
  };
</script>

<style lang="scss" scoped>
  $default-background-color: #0b8;
  $default-font-color: #fff;
  $default-background-color: #0b8;
  .cell-text-button {
    color: $default-background-color;
  }
  .nc-table {
    ::v-deep th.gutter {
      display: table-cell !important;
    }
    ::v-deep th {
      color: $default-font-color;
      background-color: $default-background-color;
      text-align: center;
      .cell {
        font-size: 12px;
        font-weight: bolder;
        font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑',
          Arial, sans-serif;
      }
    }
  }

  //::v-deep .el-input,
  //.el-select,
  //.el-date-editor,
  //.el-input-group--append {
  //  width: 100% !important;
  //}
  .table--pagination {
    padding: 8px;
    text-align: right;
    display: flex;
    justify-content: flex-end;
    ::v-deep.el-pager {
      .active {
        border-left: initial;
        background: initial;
      }
    }
  }
  .plugin-input-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
  :deep .el-table td.hightlight {
    .cell {
      color: #1890ff;
      cursor: pointer;
    }
  }
</style>
